﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace Game.Ani
{
    /// <summary>
    /// 动画播放器的增强类。
    /// </summary>
    /// <remarks>对Animation组件的动画名进行枚举和对应的值映射，辅助播放</remarks>
	public class AniController : MonoBehaviour 
	{
        Animation m_animation;

        //可能有多段动画的：
        [SerializeField]string[] idleAniNames;
        [SerializeField]string[] attackAniNames;
        [SerializeField]string[] takeDmgAniNames;
        [SerializeField]string[] deathAniNames;
        
        //基本是单段动画的：
        [SerializeField]string fightIdleAniName = "Idle";
        [SerializeField]string jumpAniName = "Jump";
        [SerializeField]string walkAniName ="Walk";
        [SerializeField]string runAniName = "Run";
        
        public enum BASE_ANI_CLIP
        {
            NULL = -1,
            idle, walk, run, attack,takeDamage, jump,
            fightIdle,
            randIdle,
            death,
        };

        void Awake()
        {
            if (!m_animation)
                m_animation = this.GetComponentInChildren<Animation>();
        }

        //****************************************************************
        //                          Private Functions
        //****************************************************************
        /// <summary>
        /// 之前播放的动画片段名
        /// </summary>
        string m_preClipName = null;
        /// <summary>
        /// 之前播放的动画类型
        /// </summary>
        BASE_ANI_CLIP m_preClipType = BASE_ANI_CLIP.NULL;
        /// <summary>
        /// 之前播放的动画的长度
        /// </summary>
        float m_preClipLength = -999;
        /// <summary>
        /// 之前播放动画的时间
        /// </summary>
        float m_preClipPlayedTime = -999;

        /// <summary>
        /// 播放片段，并给出片段类型。
        /// <para>如果动画名称非空，且已经播放过，将不予以播放</para>
        /// <para>如果是之前播放的片段类型，将不予播放</para>
        /// </summary>
        /// <param name="clipName">动画名</param>
        /// <param name="clipType">动画类型</param>
        /// <returns>片段时间</returns>
        private float PlayClip(string clipName, BASE_ANI_CLIP clipType = BASE_ANI_CLIP.NULL)
        {
            //--是否可以播放
            bool canPlay = false ;

            //类型优先，因为有可能有同类型，但是不同名的播放历史：
            if (clipType != BASE_ANI_CLIP.NULL)
            {
                if (clipType != m_preClipType)  //不同类型，则可以播放
                {
                    canPlay = true;
                }
                else if(Time.time - m_preClipPlayedTime >= m_preClipLength)//同类型，则要求时间已经过了动画长度时间
                {
                    canPlay = true;
                }
            }
            else if (!string.IsNullOrEmpty(clipName) //没有指定类型的，则是直接指定名称的，则要求名称不同
                && clipName != m_preClipName)
            {
                canPlay = true;
            }
            
            if (canPlay)
            {
                m_animation.CrossFade(clipName);

                //stop other to call play again...
                m_preClipName = clipName;
                m_preClipType = clipType;
                m_preClipLength = m_animation[clipName].length;
                m_preClipPlayedTime = Time.time;

                return m_preClipLength;
            }
            else
            {
                return 0;
            }


        }

		//---------------------------------------------------------------------------
		//				Public area
		//---------------------------------------------------------------------------
		#region Public area

        /// <summary>
        /// 播放指定类型的动画
        /// </summary>
        /// <param name="clip">片段类型</param>
        /// <param name="canLoop">是否可循环</param>
        /// <returns></returns>
        public float PlayAnimation(BASE_ANI_CLIP clip, bool canLoop = false)
        {
            string clipName = GetClipName(clip);

#if UNITY_EDITOR
            if (m_animation.GetClip(clipName) == null)
            {
                Debug.LogError("Clip not found: " + clipName);
                return -1;
            }
#endif

            //if (clipName != m_clipBefore)
            //{
                return PlayClip(clipName, clip);
            //}
            
        }

        /// <summary>
        /// 播放指定名字的动画，由调用者提供名字
        /// </summary>
        /// <param name="clipName">名字</param>
        /// <param name="canLoop">是否可循环</param>
        /// <returns></returns>
        public float PlayAnimation(string clipName, bool canLoop = false)
        {
            //由于是指定播放名字的动画，无法指定类型：
            return PlayClip(clipName, BASE_ANI_CLIP.NULL);
        }

        public float GetAnimationTime(string clipName)
        {
            return m_animation[clipName].length;
        }

        /// <summary>
        /// 当前在播放的动画片段名，可能为null
        /// </summary>
        /// <returns></returns>
        public string GetCurrAniClip()
        {
            return m_preClipName;
        }

		#endregion

        #region Private
        /// <summary>
        /// 从数组中获得随机一个string
        /// </summary>
        private string GetRandStr(string[] strs)
        {
            return strs[ Random.Range(0, strs.Length) ];
        }

        private string GetClipName(BASE_ANI_CLIP clip)
        {
            switch (clip)
            {
                case BASE_ANI_CLIP.idle:
                    return GetRandStr(idleAniNames);
                case BASE_ANI_CLIP.run:
                    return runAniName;
                case BASE_ANI_CLIP.walk:
                    return walkAniName;
                case BASE_ANI_CLIP.jump:
                    return jumpAniName;
                case BASE_ANI_CLIP.attack:
                    return GetRandStr( attackAniNames);

                case BASE_ANI_CLIP.fightIdle:
                    return fightIdleAniName;

                case BASE_ANI_CLIP.death:
                    return GetRandStr( deathAniNames );

                default:
                    Debug.LogError("Error occur. No name found for "+clip);
                    return "";
            }
        }
        #endregion
    }
}